#
# Axis Aligned Bounding Box
#
# Auther: Wesley Liu
# Email: jinvy.liu@gmail.com
# Date: 12/28/2007
#

require 'matrix'

class AABB
    # Array of 2 Vectors to indicate the two corners of the bounding box 
    attr_accessor :aabb2v
    
    def initialize(mesh=nil)
        @aabb2v = Array.new
        if mesh != nil
            computeAABB2v mesh
        end
    end
    
    def computeAABB2v mesh
        if mesh.vertices.length == 0
            raise 'mesh has no vertices!'
        end
        if @aabb2v.length == 0
            minV = mesh.vertices[0].to_a
            maxV = mesh.vertices[0].to_a
            mesh.vertices.each do |v|
                3.times do |i|
                    if v[i] < minV[i]
                        minV[i] = v[i]
                    elsif v[i] > maxV[i]
                        maxV[i] = v[i]
                    end                    
                end
            end
            @aabb2v = [Vector.elements(minV, true), Vector.elements(maxV, true)]
        end
    end
    
    def + (anotherBB)
        mergedBB = AABB.new
        if @aabb2v.length == 0 
            if anotherBB.aabb2v.length == 0
                raise 'Two aabb are all empty!'
            else
                mergedBB.aabb2v = [Vector.elements(anotherBB.aabb2v[0].to_a), Vector.elements(anotherBB.aabb2v[1].to_a)]
            end
        else
            minV = @aabb2v[0].to_a
            maxV = @aabb2v[1].to_a
            if  anotherBB.aabb2v.length > 0
                anotherMinArray = anotherBB.aabb2v[0].to_a
                anotherMaxArray = anotherBB.aabb2v[1].to_a
                3.times do |i|
                    if anotherMinArray[i] < minV[i]
                        minV[i] = anotherMinArray[i]
                    end
                    if anotherMaxArray[i] > maxV[i]
                        maxV[i] = anotherMaxArray[i]
                    end
                end
            end
            mergedBB.aabb2v = [Vector.elements(minV), Vector.elements(maxV)]
        end
        mergedBB
    end
    
    def center
        if @center == nil
            @center = Array.new
            3.times do |i|
                center[i] = (aabb2v[0][i] + aabb2v[1][i])/2
            end
        end
        @center
    end
    
    def computeCube
        if (@cubeVertices == nil || @cubeIndices == nil) && @aabb2v.length > 0
            minV = @aabb2v[0]
            maxV = @aabb2v[1]
            v00 = minV
            v01 = Vector[maxV[0], minV[1], minV[2]]
            v02 = Vector[maxV[0], maxV[1] ,minV[2]]
            v03 = Vector[minV[0], maxV[1], minV[2]]
            v10 = Vector[minV[0], minV[1], maxV[2]]
            v11 = Vector[maxV[0], minV[1], maxV[2]]
            v12 = maxV
            v13 = Vector[minV[0], maxV[1], maxV[2]]
            @cubeVertices = [v00, v01, v02, v03, v10, v11, v12, v13]
            @cubeIndices = [
                0, 1, 1, 2, 2, 3, 3, 0,
                4, 5, 5, 6, 6, 7, 7, 4,
                0, 4, 1, 5, 2, 6, 3, 7]
        end
    end
    
    def cubeVerticesPack
        if @cubeVPack == nil
            computeCube
            cubeVArray = Array.new
            @cubeVertices.each do |v|
                cubeVArray += v.to_a
            end
            @cubeVPack = cubeVArray.pack("f*")
        end
        @cubeVPack
    end
    
    def cubeIndicesPack
        if @cubeIPack == nil
            computeCube
            @cubeIPack = @cubeIndices.pack("I*")
        end
        @cubeIPack
    end
    
end

if __FILE__ == $0
    one = AABB.new
    #one.aabb2v = [Vector[0, 0, 0], Vector[1, 1, 1]]
    two = AABB.new
    two.aabb2v = [Vector[-1, -1, -1], Vector[0.5, 0.5, 0.5]]
    
    (one + two).aabb2v.each do |v|
        puts "#{v[0]} #{v[1]} #{v[2]}"
    end
    
    puts two.cubeVerticesPack.length
    puts two.cubeIndicesPack.length
end